package com.hqyj.freemovie.front.interview;

import java.util.concurrent.CountDownLatch;

//门票类
class Ticket {
    //注意这里必须使用volatile关键字修饰，保证线程的可见性。
    static volatile boolean[] flags = new boolean[3];

    //表示每天最多买1万张票
    public static final int TOTAL_NUM = 10000;

    //计数器统计目前买了多少张票
    public static int iCount = 0;
}

//售票窗口类
class SaleWindow implements Runnable {
    public int saleWindowANumber = 0; //A窗口的售票数量
    public int saleWindowBNumber = 0; //B窗口的售票数量

    public int saleWindowCNumber = 0; //C窗口的售票数量

    /*
    private CountDownLatch countDownLatch;

    public SaleWindow(CountDownLatch countDownLatch){
        this.countDownLatch = countDownLatch;
    }*/

    @Override
    public void run() {
        //不停的买票
        while (true) {
            //给Ticke的类对象上锁。保证线程同步....

            synchronized (Ticket.class) {

                //什么时候退出呢？
                if (Ticket.iCount >= Ticket.TOTAL_NUM) {
                    break;
                }

                //选择一个窗口买票...
                String threadName = Thread.currentThread().getName();
                Ticket.iCount++; //买了一张票，计数器加一。
                if ("A窗口".equals(threadName)) {
                    saleWindowANumber++;

                } else if ("B窗口".equals(threadName)) {
                    saleWindowBNumber++;
                } else {
                    saleWindowCNumber++;
                }
                System.out.println(threadName + "买了第" + Ticket.iCount + "张门票....,");
                try {
                    Thread.sleep(1);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }

            }
        }
        //退出这个while死循环是不是意味着当前线程要结束了。
        //countDownLatch.countDown(); //计数器减一；
        String temp = Thread.currentThread().getName();
        if("A窗口".equals(temp)){
            Ticket.flags[0] = true;
        }else if("B窗口".equals(temp)){
            Ticket.flags[1] = true;
        } else{
            Ticket.flags[2] = true;
        }

    }
}


public class SaleTicketDemo {

    public static void main(String[] args) {

        //参数3，表示会启动三个线程。
        //CountDownLatch countDownLatch = new CountDownLatch(3);

        //SaleWindow window = new SaleWindow(countDownLatch); //售票窗口对象。

        SaleWindow window = new SaleWindow();
        //生成三个线程
        Thread windowA = new Thread(window, "A窗口");
        Thread windowB = new Thread(window, "B窗口");
        Thread windowC = new Thread(window, "C窗口");

        //启动三个线程
        windowA.start();
        windowB.start();
        windowC.start();

        //方式一：使用join实现线程的同步，最容易想到的。
        /*
        try {
            windowA.join();
            windowB.join();
            windowC.join();
        } catch (Exception ex) {
            ex.printStackTrace();
        }*/

        //方式二：使用CountDownLatch工具类实现同步.
        /*
        try {
            countDownLatch.await();
        }catch (Exception ex){
            ex.printStackTrace();
        }*/

        //方式三：利用了volatile可见性来控制线程的同步。
        //通过死循环判断子线程是否结束
        for(int i=0;i<Ticket.flags.length;){
            if(Ticket.flags[i]){
                i++;
            }
        }

        //统计三个窗口的售票数量
        System.out.println("A窗口卖了：" + window.saleWindowANumber + "张门票....");
        System.out.println("B窗口卖了：" + window.saleWindowBNumber + "张门票....");
        System.out.println("C窗口卖了：" + window.saleWindowCNumber + "张门票....");


    }
}
